package core;

import java.awt.Color;

import boundary.UI;
import dto.*;
import entity.Account;
import entity.fields.*;
import entity.fields.properties.Brewery;
import entity.fields.properties.Shipping;
import entity.fields.properties.Street;
import entity_controllers.Card;
import entity_controllers.OptionManager;
import entity_controllers.cards.BalanceCard;
import entity_controllers.cards.BuildingTaxCard;
import entity_controllers.cards.GotoJailCard;
import entity_controllers.cards.FreeJailCard;
import entity_controllers.cards.MatadorGrant;
import entity_controllers.cards.MoveCard;
import entity_controllers.fieldcontrollers.*;
import entity_controllers.options.BuyHouseOption;
import entity_controllers.options.EndTurnOption;
import entity_controllers.options.SellHouseOption;
import entity_controllers.options.ShakeMoveOption;
import entity_controllers.options.effects.JailEffect;
import entity_controllers.options.effects.MoveEffect;
import ie.Shaker;

public class Creator {
	
	private SubCreator subCreator;
	private static Creator instance;

	public static Creator getInstance() {
		if (instance == null) {
			instance = new Creator();
		}
		return instance;
	}

	public static void init(SubCreator subCreator) {
		getInstance().subCreator = subCreator;
	}

	public static SubCreator get() {
		return getInstance().subCreator;
	}

	public static Field[] createFields() {
		// create fields

		Field[] fields = {
				/* 0 */new Start("Start", new StartController()),
				/* 1 */new Street("Rødovrevej", Color.BLUE, 1200, 50, 250, 750, 2250, 4000, 6000, 1000, new StreetController()),
				/* 2 */new Chance("Prøv Lykken", new ChanceController(Creator.createCardList())),
				/* 3 */new Street("Hvidovrevej", Color.BLUE, 1200, 50, 250, 750, 2250, 4000, 6000, 1000, new StreetController()),
				/* 4 */new Tax("Indkomstskat", 4000, true, new TaxController()),
				/* 5 */new Shipping("Helsingør-Helsingborg", 4000, new ShippingController()),
				/* 6 */new Street("Roskildevej", Color.ORANGE, 2000, 100, 600, 1800, 5400, 8000, 11000, 1000, new StreetController()),
				/* 7 */new Chance("Prøv Lykken", new ChanceController()),
				/* 8 */new Street("Valby Langgade", Color.ORANGE, 2000, 100, 600, 1800, 5400, 8000, 11000, 1000, new StreetController()),
				/* 9 */new Street("Allégade", Color.ORANGE, 2400, 150, 800, 2000, 6000, 9000, 12000, 1000, new StreetController()),
				/* 10 */new Jail("Fængsel", false, new JailController()),
				/* 11 */new Street("Frederiksberg Allé", Color.GREEN, 2800, 200, 1000, 3000, 9000, 12500, 15000, 2000, new StreetController()),
				/* 12 */new Brewery("Tuborg Bryggeriet", 3000, new BreweryController()),
				/* 13 */new Street("Bülowsvej", Color.GREEN, 2800, 200, 1000, 3000, 9000, 12500, 15000, 2000, new StreetController()),
				/* 14 */new Street("Gl. Kongevej", Color.GREEN, 3200, 250, 1250, 3750, 10000, 14000, 18000, 2000, new StreetController()),
				/* 15 */new Shipping("Mols-linien", 4000, new ShippingController()),
				/* 16 */new Street("Bernstorffsvej", Color.GRAY, 3600, 300, 1400, 4000, 11000, 15000, 19000, 2000, new StreetController()),
				/* 17 */new Chance("Prøv Lykken", new ChanceController()),
				/* 18 */new Street("Hellerupvej", Color.GRAY, 3600, 300, 1400, 4000, 11000, 15000, 19000, 2000, new StreetController()),
				/* 19 */new Street("Strandvejen", Color.GRAY, 4000, 350, 1600, 4400, 12000, 16000, 20000, 2000, new StreetController()),
				/* 20 */new Refuge("Gratis Parkering", new RefugeController()),
				/* 21 */new Street("Trianglen", Color.RED, 4400, 350, 1800, 5000, 14000, 17500, 21000, 3000, new StreetController()),
				/* 22 */new Chance("Prøv Lykken", new ChanceController()),
				/* 23 */new Street("Østerbrogade", Color.RED, 4400, 350, 1800, 5000, 14000, 17500, 21000, 3000, new StreetController()),
				/* 24 */new Street("Grønningen", Color.RED, 4800, 400, 2000, 6000, 15000, 18500, 22000, 3000, new StreetController()),
				/* 25 */new Shipping("Gedser-Rostock", 4000, new ShippingController()),
				/* 26 */new Street("Bredgade", Color.WHITE, 5200, 450, 2200, 6600, 16000, 19500, 23000, 3000, new StreetController()),
				/* 27 */new Street("Kgs. Nytorv", Color.WHITE, 5200, 450, 220, 6600, 16000, 19500, 23000, 3000, new StreetController()),
				/* 28 */new Brewery("Carlsberg Bryggeriet", 3000, new BreweryController()),
				/* 29 */new Street("Østergade", Color.WHITE, 5600, 500, 2400, 7200, 17000, 20500, 24000, 3000, new StreetController()),
				/* 30 */new Jail("De fængsles", true, new JailController()),
				/* 31 */new Street("Amagertorv", Color.YELLOW, 6000, 550, 2600, 7800, 18000, 22000, 25500, 4000, new StreetController()),
				/* 32 */new Street("Vimmelskaftet", Color.YELLOW, 6000, 550, 2600, 7800, 18000, 22000, 25500, 4000, new StreetController()),
				/* 33 */new Chance("Prøv Lykken", new ChanceController()),
				/* 34 */new Street("Nygade", Color.YELLOW, 6400, 600, 3000, 9000, 20000, 24000, 28000, 4000, new StreetController()),
				/* 35 */new Shipping("Rødby-Puttgarden", 4000, new ShippingController()),
				/* 36 */new Chance("Prøv Lykken", new ChanceController()),
				/* 37 */new Street("Frederiksberggade", new Color(150, 60, 150), 7000, 700, 3500, 10000, 22000, 26000, 30000, 4000, new StreetController()),
				/* 38 */new Tax("Luksusskat", 2000, false, new TaxController()),
				/* 39 */new Street("Rådhuspladsen", new Color(150, 60, 150), 8000, 1000, 4000, 12000, 28000, 34000, 40000, 4000, new StreetController()), };
		if (get() != null && get().createFields() != null)
			fields = get().createFields();
		// show fields in UI
		UI.get().createFields(fields);

		// update fieldboard
		return fields;
	}

	public static Player[] createPlayers(int startingBalance) {
		int numberOfPlayers;
		do {
			// get number of players from UI
			numberOfPlayers = UI.get().getInteger("Vælg antal spillere"); // chance null to string
		} while (numberOfPlayers < 2 || numberOfPlayers > 6);

		// create player list
		Player[] players = new Player[numberOfPlayers];

		// create each player
		for (int i = 0; i < numberOfPlayers; i++) {
			String name = "";
			do {
				// only allow non-picked name
				name = UI.get().getString("Indtast navn for spiller " + (i + 1)); // chance null to string
				// System.out.println(name);
			} while (name.isEmpty() || nameIsNotUsed(name, players));
			// Create player's Account
			Account account = new Account(startingBalance);
			OptionManager om = account.getOM();

			om.addOption(new ShakeMoveOption("Kast"));
			om.getOption(ShakeMoveOption.class).enable();
			om.addOption(new EndTurnOption("Afslut tur"));
			om.addOption(new BuyHouseOption("Buy House"));
			om.addOption(new SellHouseOption("Sell House"));

			account.getEM().addOption(new MoveEffect("f"));
			account.getEM().getOption(MoveEffect.class).enable();
			account.getEM().addOption(new JailEffect("a"));
			if (get() != null && get().createAccount() != null)
				account = get().createAccount();
			// create player
			players[i] = new Player(name, account);
		}

		// show players in UI
		UI.get().showPlayers(players);

		// update playerboard
		return players;
	}

	public static Card[] createCardList() {
		Card[] cards = {
				/* 0 */new BalanceCard("Kommunen har eftergivet et kvartals skat. Hæv i banken 3.000.", 3000),
				/* 1 */new BalanceCard("Grundet dyrtiden har De fået gageforhøjelse. Modtag 1.000.", 1000),
				/* 2 */new BalanceCard("De har solgt nogle gamle møbler på auktion. Modtag 1.000 af banken.", 1000),
				/* 3 */new BalanceCard("Deres præmieobligation er udtrukket. De modtager 1.000 af banken.", 1000),
				/* 4 */new BalanceCard("Deres præmieobligation er udtrukket. De modtager 1.000 af banken.", 1000),
				/* 5 */new BalanceCard("Modtag udbytte af Deres aktier - 1.000.", 1000),
				/* 6 */new BalanceCard("Modtag udbytte af Deres aktier - 1.000.", 1000),
				/* 7 */new BalanceCard("De modtager Deres aktieudbytte. Modtag 1.000 af banken.", 1000),
				/* 8 */new BalanceCard("De havde en række med elleve rigtige i tipning. Modtag 1.000.", 1000),
				/* 9 */new BalanceCard("De har vundet i Klasselotteriet. Modtag 500.", 500),
				/* 10 */new BalanceCard("De har vundet i Klasselotteriet. Modtag 500.", 500),
				/* 11 */new BalanceCard("Værdien af egen avl fra nyttehaven udgør 200, som De modtager af banken.", 200),

				/* 12 */new BalanceCard("Betal 3.000 for reperation af Deres vogn.", -3000),
				/* 13 */new BalanceCard("Betal 3.000 for reperation af Deres vogn.", -3000),
				/* 14 */new BalanceCard("De har modtaget Deres tandlægeregning. Betal 2.000.", -2000),
				/* 15 */new BalanceCard("De er kørt frem for \"Fuldt stop\". Betal 1.000 i bøde.", -1000),
				/* 16 */new BalanceCard("De har købt 4 nye dæk til Deres vogn. Betal 1.000.", -1000),
				/* 17 */new BalanceCard("Betal Deres bilforsikring - 1.000.", -1000),
				/* 18 */new BalanceCard("Betal for vognvask og smøring 300.", -300),
				/* 19 */new BalanceCard("De har fået en parkeringsbøde. Betal 200 i bøde.", -200),
				/* 20 */new BalanceCard("De har været en tur i udlandet of haft for mange cigaretter med hjem. Betal told 200.", -200),
				/* 21 */new BalanceCard("Betal 200 for levering af 2 kasser øl.", -200),

				/* 22 */new BalanceCard("De har lagt penge ud til et sammenskudsgilde. Mærkværdigvis betaler alle straks. Modtag fra hver medspiller 500.", 500, true),
				/* 23 */new BalanceCard("De skal holde familiefest og får tilskud fra hver medspiller på 500.", 500, true),
				/* 24 */new BalanceCard("Det er Deres fødselsdag. Modtag af hver medspiller 200.", 200, true),

				/* 25 */new MoveCard("Ryk tre felter frem.", 3),
				/* 26 */new MoveCard("Ryk tre felter tilbage.", -3),
				/* 27 */new MoveCard("Ryk tre felter tilbage.", -3),
				/* 28 */new MoveCard("Ryk tre felter tilbage.", -3),

				/* 29 */new MoveCard("Ryk frem til \"Start\".", 0, true), // Start
				/* 30 */new MoveCard("Ryk frem til \"Start\".", 0, true), // Start
				/* 31 */new MoveCard("Tag ind på Rådhuspladsen.", 39, true), // R�dhuspladsen
				/* 32 */new MoveCard("Ryk frem til Strandvejen.", 19, true), // Strandvejen
				/* 33 */new MoveCard("Ryk frem til Vimmelskaftet", 32, true), // Vimmelskaftet
				/* 34 */new MoveCard("Ryk frem til Grønningen.", 24, true), // Gr�nningen
				/* 35 */new MoveCard("Ryk frem til Frederiksberg Allé.", 11, true), // Frederiksberg All�
				/* 36 */new MoveCard("Tag med Mols-Linien.", 15, true), // Mols-linien
				/* 37 */new MoveCard("Tag med nærmeste færge.", Shipping.class), // N�rmeste Rederi
				
				/* 38 */new MoveCard("Ryk brikken frem til det nærmeste rederi og betal ejeren to gange den leje, han ellers er berettiget til.", Shipping.class, true), // N�rmeste Rederi
				/* 39 */new MoveCard("Ryk brikken frem til det nærmeste rederi og betal ejeren to gange den leje, han ellers er berettiget til.", Shipping.class, true), // N�rmeste Rederi

				/* 38 */new FreeJailCard(), // Out of Jail
				/* 39 */new FreeJailCard(),

				/* 40 */new GotoJailCard("Gå i fængsel. Ryk direkte til fængslet. Selv om De paserer \"Start\", indkasserer De ikke 4000."),
				/* 41 */new GotoJailCard("Gå i fængsel. Ryk direkte til fængslet. Selv om De paserer \"Start\", indkasserer De ikke 4000."),

				/* 42 */new BuildingTaxCard("Oliepriserne er steget, og De skal betale: 500 pr. hus og 2.000 pr. hotel", 500, 2000),
				/* 43 */new BuildingTaxCard("Ejendomsskatterne er steget. Ekstraudgifter er: 800 pr. hus og 2.300 pr. hotel", 800, 2300),

				/* 44 */new MatadorGrant("De modtager \"Matador-legatet for værdigt trængende\" på 40.000. Ved værdigt trængende forstås, at Deres formue, dvs. Deres kontante penge + skøder + bygninger, ikke overstiger 15.000."),

		};

		if (get() != null && get().createCards() != null)
			cards = get().createCards();

		return cards;
	}

	private static boolean nameIsNotUsed(String name, Player[] players) {
		for (int i = 0; i < players.length; i++) {
			if (players[i] != null)
				// if another player has the name, return true
				if (name.equals(players[i].getName()))
					return true;
		}
		return false;
	}

	public static Dice[] createDices() {
		Dice[] dice = new Shaker(2, 6).getDices();
		if (get() != null && get().createDices() != null) {
			dice = get().createDices();
		}
		return dice;
	}
	
}
